package alp.starcode.nudtportal.framework.util;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class SignUtil {

    /**
     * 使用 Map按key进行排序
     *
     * @param map
     * @return
     */
    public static Map<String, String> sortMapByKey(Map<String, String> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        //升序排序
        Map<String, String> sortMap = new TreeMap<>(String::compareTo);
        sortMap.putAll(map);
        return sortMap;
    }

    /**
     * 替换特殊字符
     * @param input 文本
     * @return
     */
    public static String removeQuotes(String input){
        Pattern pattern = Pattern.compile("^\"(.*?)\"$");
        Matcher matcher = pattern.matcher(input);
        if (matcher.matches()){
            return matcher.group(1);
        }
        return input;
    }
    /**
     * 签名加密
     * @param request
     * @param secretKey 密钥key
     * @param timestamp 时间戳
     * @param nonce 随机值
     * @param token token
     * @return
     */
    public static String sign(HttpServletRequest request, String secretKey, String timestamp, String nonce, String token) {
        //获取RequestBody参数，此处需要配合过滤器处理request后才能获取
        String bodyParam = null;
        if (request instanceof ContentCachingRequestWrapper) {
            bodyParam = new String(((ContentCachingRequestWrapper) request).getContentAsByteArray(), StandardCharsets.UTF_8);
            //将json排序后转换
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode jsonNode = objectMapper.readTree(bodyParam);
                //将参数排序
                if (jsonNode.isObject()) {
                    ObjectNode objectNode = (ObjectNode) jsonNode;
                    List<String> keyValueStrings = new ArrayList<>();

                    objectNode.fields().forEachRemaining(entry -> {
                        String keyValueString = entry.getKey() + StringEscapeUtils.unescapeJava(removeQuotes(entry.getValue().toString()));
                        keyValueStrings.add(keyValueString);
                    });
                    keyValueStrings.sort(String::compareTo); // Sort the strings
                    bodyParam = String.join("", keyValueStrings);

                }
            } catch (Exception e) {
                log.error("签名失败：" + e);
                bodyParam = null;
            }
        }

        //获取RequestParam参数
        Map<String, String[]> requestParameterMap = request.getParameterMap();

        //获取PathVariable参数
        ServletWebRequest webRequest = new ServletWebRequest(request, null);
        Map<String, String> requestPathMap = (Map<String, String>) webRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);

        //定义参数字符串
        StringBuilder sb = new StringBuilder();
        if (CharSequenceUtil.isNotBlank(bodyParam)) {
            sb.append(bodyParam);
        }

        //解析RequestParam参数
        if (!CollectionUtils.isEmpty(requestParameterMap)) {
            requestParameterMap.entrySet()
                    .stream()
                    .sorted(Map.Entry.comparingByKey())
                    .forEach(paramEntry -> {
                        String paramValue = String.join("", Arrays.stream(paramEntry.getValue()).sorted().toArray(String[]::new));
                        sb.append(paramEntry.getKey()).append(paramValue);
                    });
        }

        //解析PathVariable参数
        if (ArrayUtil.isNotEmpty(requestPathMap)) {
            List<String> pathVariableStrings = new ArrayList<>();

            for (String key : requestPathMap.keySet()) {
                pathVariableStrings.add(key + requestPathMap.get(key));
            }
            pathVariableStrings.sort(String::compareTo);
            // 排序
            bodyParam = String.join("", pathVariableStrings);
            sb.append(bodyParam);
        }

        //加密并且返回
        return SecureUtil.md5(sb + token + secretKey + timestamp + nonce).toUpperCase();
    }


}
